﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Audio;

namespace AnimalWars2
{
    public class GameTable : GameScreen
    {
        public Texture2D m_Background;
        protected SoundEffect m_TableSoundEffect;
        protected SoundEffectInstance m_TableSoundEffectInstance;

        int m_iUpperPlayerScore;
        int m_iLowerPlayerScore;

        // atributos de controle do tempo do jogo
        DateTime m_StartGameTime;
        int m_MaxRoundTime = 60;
        int m_ElapsedGameTime;
        
        // outros atributos
        public VisualizationMode m_VisualizationMode;
        public bool m_bKeyPressed;

        public List<Entity> m_Entities = new List<Entity>();

        public GameTable(Game GameRef, VisualizationMode initialVisualizationMode)
            : base(GameRef)
        {
            m_VisualizationMode = initialVisualizationMode;
        }

        public override void LoadContent()
        {
            m_Background = m_Game.Content.Load<Texture2D>(Constants.BACKGROUND_ASSET_NAME);
            Texture2D player1 = m_Game.Content.Load<Texture2D>(Constants.PLAYER1_THUMNAIL_ASSET_NAME);
            Texture2D player2 = m_Game.Content.Load<Texture2D>(Constants.PLAYER2_THUMNAIL_ASSET_NAME);

            AddEntity(new PenguinPlayer(this, player1,
                                   new Vector2(0.0f, Constants.TABLE_BOTTON_LIMIT + Constants.PLAYER_DISPLACEMENT), new Vector2(0.0f, 0.0f), LowerPlayer.MoveLeft, LowerPlayer.MoveRight, LowerPlayer.Action, PlayerSide.Down));

            AddEntity(new AntPlayer(this, player2,
                                   new Vector2(0.0f, Constants.TABLE_TOP_LIMIT - Constants.PLAYER_DISPLACEMENT), new Vector2(0.0f, 0.0f), UpperPlayer.MoveLeft, UpperPlayer.MoveRight, UpperPlayer.Action, PlayerSide.Up));

            float fPosition = (Constants.TABLE_RIGHT_LIMIT - Constants.TABLE_LEFT_LIMIT) * 0.2f;
            Texture2D ballTexture = m_Game.Content.Load<Texture2D>(Constants.BALL_ASSET_NAME);

            for (int i = -2; i < 3; i++)
            {
                AddEntity(new Ball(this, ballTexture,
                          new Vector2(fPosition * i, Constants.TABLE_BOTTON_LIMIT), new Vector2(0.0f, 0.0f), BallState.Stopped));

                AddEntity(new Ball(this, ballTexture,
                          new Vector2(fPosition * i, Constants.TABLE_TOP_LIMIT), new Vector2(0.0f, 0.0f), BallState.Stopped));
            }

            m_TableSoundEffect = m_Game.Content.Load<SoundEffect>(Constants.GAME_TABLE_SOUND_ASSET_NAME);
            m_TableSoundEffectInstance = m_TableSoundEffect.CreateInstance();
            m_TableSoundEffectInstance.IsLooped = true;

            if (Constants.PLAY_SOUND)
            {
                m_TableSoundEffectInstance.Play();
            }
        }

        public override void UnloadContent() { }

        // incializacao necessaria para o inicio do jogo
        public void startGame()
        {
            m_StartGameTime = DateTime.Now;
        }

        public void RestartGame()
        {
            //coloca as bolas na posição original
            float fPosition = (Constants.TABLE_RIGHT_LIMIT - Constants.TABLE_LEFT_LIMIT) * 0.2f;
            int upperBalls = (int)(Constants.TOTAL_BALLS * 0.5f);
            int lowerBalls = upperBalls;
            int i = -2;
            int count = i;

            foreach (Entity Current in m_Entities)
            {
                Ball ball = Current as Ball;

                if (ball != null)
                {
                    if (upperBalls != 0)
                    {
                        ball.m_Pos = new Vector2(fPosition * count, Constants.TABLE_TOP_LIMIT);
                        ball.m_Vel = new Vector2(0.0f, 0.0f);
                        ball.m_BallState = BallState.Stopped;

                        upperBalls--;
                        count++;

                        if (upperBalls == 0)
                            count = i;
                    }
                    else if (lowerBalls != 0)
                    {
                        ball.m_Pos = new Vector2(fPosition * count, Constants.TABLE_BOTTON_LIMIT);
                        ball.m_Vel = new Vector2(0.0f, 0.0f);
                        ball.m_BallState = BallState.Stopped;

                        lowerBalls--;
                        count++;

                        if (lowerBalls == 0)
                            count = i;
                    }
                }
            }

            //inicia um novo jogo
            startGame();
        }

        public void AddEntity(Entity NewEntity)
        {
            m_Entities.Add(NewEntity);
        }

        public override void Update(GameTime gameTime)
        {
            //modo de visão = perspectiva ou top-down
            KeyboardState oKS = Keyboard.GetState();
            bool selected = oKS.IsKeyDown(Keys.F12);

            if (!m_bKeyPressed && selected)
            {
                m_VisualizationMode = GameUtilities.InvertVisualizationMode(m_VisualizationMode);
            }

            m_bKeyPressed = selected;

            //update das entidades
            List<Entity> EntitiesCopy = new List<Entity>(m_Entities);

            foreach (Entity Current in EntitiesCopy)
            {
                Current.Update(gameTime);
            }

            // contagem regressiva do jogo
            m_ElapsedGameTime = m_MaxRoundTime - (int)(DateTime.Now - m_StartGameTime).Seconds;

            ScoreType scoreType = VerifyGameEnd((int)(DateTime.Now - m_StartGameTime).Seconds == m_MaxRoundTime);
            if (scoreType != ScoreType.NotFinished)
            {
                if (scoreType == ScoreType.LowerPlayerVictory)
                    m_iLowerPlayerScore++;
                else if (scoreType == ScoreType.UpperPlayerVictory)
                    m_iUpperPlayerScore++;

                RestartGame();
            }
        }

        // imprime o tempo restante do jogo
        protected void drawElapsedGameTime(GameTime gameTime, SpriteBatch spriteBatch)
        {
            TimeSpan elapsedGameTime = m_StartGameTime - DateTime.Now;

            StringUtils.DrawString(m_Game.m_Font, spriteBatch, m_ElapsedGameTime.ToString(), 424, 31);
        }

        protected void drawBackground(GameTime gameTime, SpriteBatch spriteBatch)
        {
            Vector2 position = new Vector2((Constants.WINDOW_WIDTH - m_Background.Bounds.Width) * 0.5f, (Constants.WINDOW_HEIGHT - m_Background.Bounds.Height) * 0.5f);

            spriteBatch.Draw(m_Background,
                position, //new Vector2(0.0f, 0.0f),
                null,
                new Color(1.0f, 1.0f, 1.0f, 1.0f),
                0.0f,
                new Vector2(0.0f, 0.0f),
                1.0f,
                SpriteEffects.None,
                0.7f);

            //spriteBatch.Draw(m_Background,
            //    m_Game.m_Camera.TransformPos(position),
            //    null,
            //    new Color(1.0f, 1.0f, 1.0f, 1.0f),
            //    0.0f,
            //    new Vector2(m_Background.Bounds.X, m_Background.Bounds.Y) * 0.5f,
            //    m_Game.m_Camera.TransformScale(position, new Vector2(1.0f, 1.0f)),
            //    SpriteEffects.None,
            //    0.7f);
        }

        public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            drawBackground(gameTime, spriteBatch);
            drawElapsedGameTime(gameTime, spriteBatch);

            m_Game.DrawLine(spriteBatch, m_Game.m_Camera.TransformPos(new Vector2(Constants.TABLE_LEFT_LIMIT, Constants.TABLE_TOP_LIMIT)), m_Game.m_Camera.TransformPos(new Vector2(Constants.TABLE_RIGHT_LIMIT, Constants.TABLE_TOP_LIMIT)), Color.Red, 0.7f);
            m_Game.DrawLine(spriteBatch, m_Game.m_Camera.TransformPos(new Vector2(Constants.TABLE_LEFT_LIMIT, Constants.TABLE_BOTTON_LIMIT)), m_Game.m_Camera.TransformPos(new Vector2(Constants.TABLE_RIGHT_LIMIT, Constants.TABLE_BOTTON_LIMIT)), Color.Red, 0.7f);

            m_Game.DrawLine(spriteBatch, m_Game.m_Camera.TransformPos(new Vector2(Constants.TABLE_RIGHT_LIMIT, Constants.TABLE_TOP_LIMIT)), m_Game.m_Camera.TransformPos(new Vector2(Constants.TABLE_RIGHT_LIMIT, Constants.TABLE_BOTTON_LIMIT)), Color.Red, 0.7f);
            m_Game.DrawLine(spriteBatch, m_Game.m_Camera.TransformPos(new Vector2(Constants.TABLE_LEFT_LIMIT, Constants.TABLE_TOP_LIMIT)), m_Game.m_Camera.TransformPos(new Vector2(Constants.TABLE_LEFT_LIMIT, Constants.TABLE_BOTTON_LIMIT)), Color.Red, 0.7f);

            foreach (Entity Current in m_Entities)
            {
                Current.Draw(gameTime, spriteBatch);
            }
        }

        public ScoreType VerifyGameEnd(bool timeEnded)
        {
            ScoreType scoreType = ScoreType.NotFinished;
            int UpperPlayerBalls = 0;
            int LowerPlayerBalls = 0;

            foreach (Entity Current in m_Entities)
            {
                Ball ball = Current as Ball;

                if (ball != null)
                {
                    if (ball.m_Pos.Y == Constants.TABLE_TOP_LIMIT)
                        UpperPlayerBalls++;
                    else if (ball.m_Pos.Y == Constants.TABLE_BOTTON_LIMIT)
                        LowerPlayerBalls++;
                }
            }

            if (!timeEnded)
            {
                if (LowerPlayerBalls + UpperPlayerBalls != Constants.TOTAL_BALLS)
                {
                    scoreType = ScoreType.NotFinished;
                }
                else if (LowerPlayerBalls == Constants.TOTAL_BALLS)
                {
                    scoreType = ScoreType.UpperPlayerVictory;
                }
                else if (UpperPlayerBalls == Constants.TOTAL_BALLS)
                {
                    scoreType = ScoreType.LowerPlayerVictory;
                }
            }
            else
            {
                if (LowerPlayerBalls < UpperPlayerBalls)
                    scoreType = ScoreType.LowerPlayerVictory;
                else if (UpperPlayerBalls < LowerPlayerBalls)
                    scoreType = ScoreType.UpperPlayerVictory;
                else
                    scoreType = ScoreType.Draw;
            }

            return scoreType;
        }
    }
}
